package sg.edu.nus.iss.ooad.jass.ui;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import sg.edu.nus.iss.ooad.jass.controller.CompanyController;
import sg.edu.nus.iss.ooad.jass.controller.JobAdvertisementController;
import sg.edu.nus.iss.ooad.jass.controller.MainController;
import sg.edu.nus.iss.ooad.jass.controller.ResponseController;
import sg.edu.nus.iss.ooad.jass.entity.Company;
import sg.edu.nus.iss.ooad.jass.entity.JobAdvertisement;
import sg.edu.nus.iss.ooad.jass.ui.widget.AbstractJASSRegularWindow;
import sg.edu.nus.iss.ooad.jass.ui.widget.JASSRegularPanel;

/**
 *
 * Update Job Advertisement Form.
 *
 * @author Isak Rabin (HT082193M)
 * @version 1.0
 * @since 1.0
 * 
 *
 */
public class AdvertiserUpdateJobAdvertisementForm extends AbstractJASSRegularWindow {

        private static final long serialVersionUID = 6732995790214782858L;
        private final static Logger logger = Logger.getLogger(AdvertiserCreateJobAdvertisementForm.class.getName());
        //Form Components
        private Label labelErrorMessage = null;
        private Label labelCompanyID = null;
        private Label labelCompanyName = null;
        private Label labelStartDate = null;
        private Label labelFinishDate = null;
        private Label labelJobTitle = null;
        private Label labelJobDescription = null;
        private Label labelJobLocation = null;
        private Label labelJobStartDate = null;
        private Label labelCompanyDepartment = null;
        private Label labelTechnicalSkills = null;
        private Label labelManagementSkills = null;
        private Label labelMinSalary = null;
        private Label labelMaxSalary = null;
        private Label labelNoteMsg = null;
        private String labelStatusMsg = null;
        private TextField textCompanyID = null;
        private TextField textStartDate = null;
        private TextField textFinishDate = null;
        private TextField textJobTitle = null;
        private TextArea textJobDescription = null;
        private TextField textJobLocation = null;
        private TextField textJobStartDate = null;
        private TextField textCompanyDepartment = null;
        private TextArea textTechnicalSkills = null;
        private TextArea textManagementSkills = null;
        private TextField textMinSalary = null;
        private TextField textMaxSalary = null;
        private Button btnSearchCompany = null;
        private Button btnUpdate = null;
        private Button btnWithdraw = null;
        private Button btnDelete = null;
        private Button btnCancel = null;
        private Button btnReset = null;
        private Button btnEdit = null;
        private Button btnViewResponse = null;
        private JASSRegularPanel formPanel = null;
        private Panel inputPanel = null;
        private Panel buttonPanel = null;
        private Panel notePanel = null;
        private GridBagLayout inputLayout = null;
        //Parent Window
        private AbstractJASSRegularWindow parent = null;
        //Data
        private Company company = null;
        private JobAdvertisement jobadvertisement = null;
        /**
         * Singleton instance
         */
        public static AdvertiserUpdateJobAdvertisementForm instance = null;

        /**
         * Constructor AdvertiserUpdateJobAdvertisementForm
         */
        public AdvertiserUpdateJobAdvertisementForm(AbstractJASSRegularWindow parent) {
                super("Job Advertisement and Search System", new Dimension(640, 480));
                this.parent = parent;
                initComponents();
                setResizable(false);
              
        }

        /**
         * Singleton method to get the instanct of AdvertiserUpdateJobAdvertisementForm
         * @param parent
         * @return
         */
        public static AdvertiserUpdateJobAdvertisementForm getInstance(AbstractJASSRegularWindow parent) {

                if (instance == null) {
                        instance = new AdvertiserUpdateJobAdvertisementForm(parent);
                }
                return instance;
        }

        /**
         * Initialize form components
         */
        private void initComponents() {
                //initiate all Components
                labelNoteMsg = new Label("Press 'Edit' to update ", Label.CENTER);
                labelNoteMsg.setForeground(Color.RED);
                labelErrorMessage = new Label("", Label.LEFT);
                labelErrorMessage.setForeground(Color.RED);
                labelCompanyID = new Label("Company ID", Label.LEFT);
                labelCompanyName = new Label("", Label.LEFT);
                labelStartDate = new Label("Ads. Start Date (dd/MM/yyyy)", Label.LEFT);
                labelFinishDate = new Label("Ads. Finish Date (dd/MM/yyyy)", Label.LEFT);
                labelJobTitle = new Label("Job Title", Label.LEFT);
                labelJobDescription = new Label("Job Description", Label.LEFT);
                labelJobLocation = new Label("Job Location", Label.LEFT);
                labelJobStartDate = new Label("Job Start Date (dd/MM/yyyy)", Label.LEFT);
                labelCompanyDepartment = new Label("Company Department", Label.LEFT);
                labelTechnicalSkills = new Label("Technical Skills", Label.LEFT);
                labelManagementSkills = new Label("Management Skills", Label.LEFT);
                labelMinSalary = new Label("Min. Salary", Label.LEFT);
                labelMaxSalary = new Label("Max. Salary", Label.LEFT);
                textCompanyID = new TextField(5);
                textStartDate = new TextField(15);
                textFinishDate = new TextField(15);
                textJobTitle = new TextField(35);
                textJobDescription = new TextArea(5, 35);
                textJobLocation = new TextField(35);
                textJobStartDate = new TextField(15);
                textCompanyDepartment = new TextField(35);
                textTechnicalSkills = new TextArea(5, 25);
                textManagementSkills = new TextArea(5, 25);
                textMinSalary = new TextField(15);
                textMaxSalary = new TextField(15);
                btnSearchCompany = new Button("...");
                btnEdit = new Button("Edit");
                btnUpdate = new Button("Save");
                btnCancel = new Button("Cancel");
                btnReset = new Button("Reset");
                btnWithdraw = new Button("Withdraw");
                btnDelete = new Button("Delete");
                btnViewResponse = new Button("Responses");
                buttonPanel = new Panel();
                inputPanel = new Panel();
                formPanel = new JASSRegularPanel("Update Job Advertisement");

                //set the action listener
                btnSearchCompany.addActionListener(new SearchCompanyActionListener());
                btnEdit.addActionListener(new EditActionListener());
                btnUpdate.addActionListener(new UpdateActionListener());
                btnCancel.addActionListener(new CancelActionListener());
                btnReset.addActionListener(new ResetActionListener());
                btnWithdraw.addActionListener(new WithdrawActionListener());
                btnDelete.addActionListener(new DeleteActionListener());
                btnViewResponse.addActionListener(new ViewResponsesActionListener());

                //set Layout
                buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
                buttonPanel.add(btnUpdate);
                buttonPanel.add(btnReset);
                buttonPanel.add(btnCancel);
                buttonPanel.add(btnWithdraw);
                buttonPanel.add(btnDelete);
                buttonPanel.add(btnViewResponse);
                buttonPanel.add(btnEdit);


                inputLayout = new GridBagLayout();
                inputPanel.setLayout(inputLayout);

                attachComponent(labelErrorMessage, 0, 0, 8, 1);
                attachComponent(labelCompanyID, 0, 1, 1, 1);
                attachComponent(textCompanyID, 1, 1, 1, 1);
                attachComponent(btnSearchCompany, 2, 1, 1, 1);
                attachComponent(labelStartDate, 6, 1, 1, 1);
                attachComponent(textStartDate, 7, 1, 2, 1);
                attachComponent(labelCompanyName, 1, 2, 5, 1);
                attachComponent(labelFinishDate, 6, 2, 1, 1);
                attachComponent(textFinishDate, 7, 2, 2, 1);

                attachComponent(labelJobTitle, 0, 3, 1, 1);
                attachComponent(textJobTitle, 1, 3, 8, 1);

                attachComponent(labelJobDescription, 0, 4, 1, 1);
                attachComponent(textJobDescription, 1, 4, 8, 4);
                attachComponent(labelJobLocation, 0, 8, 1, 1);
                attachComponent(textJobLocation, 1, 8, 6, 1);
                attachComponent(labelJobStartDate, 0, 9, 1, 1);
                attachComponent(textJobStartDate, 1, 9, 5, 1);
                attachComponent(labelCompanyDepartment, 0, 10, 1, 1);
                attachComponent(textCompanyDepartment, 1, 10, 7, 1);
                attachComponent(labelTechnicalSkills, 0, 11, 1, 1);
                attachComponent(textTechnicalSkills, 1, 11, 8, 4);
                attachComponent(labelManagementSkills, 0, 15, 1, 1);
                attachComponent(textManagementSkills, 1, 15, 8, 4);
                attachComponent(labelMinSalary, 0, 18, 1, 1);
                attachComponent(textMinSalary, 1, 18, 1, 1);
                attachComponent(labelMaxSalary, 2, 18, 1, 1);
                attachComponent(textMaxSalary, 3, 18, 1, 1);

                attachComponent(labelMinSalary, 0, 20, 1, 1);
                attachComponent(textMinSalary, 1, 20, 1, 1);
                attachComponent(labelMaxSalary, 2, 20, 1, 1);
                attachComponent(textMaxSalary, 3, 20, 1, 1);

                notePanel = new Panel();
                notePanel.setLayout(new BorderLayout(5, 5));
                notePanel.add(buttonPanel, BorderLayout.NORTH);
                notePanel.add(labelNoteMsg, BorderLayout.SOUTH);

                formPanel.add(inputPanel, BorderLayout.CENTER);
                formPanel.add(notePanel, BorderLayout.SOUTH);

                //add to the frame
                add(formPanel);
                pack();
        }

        /**
         * To initialize the data. 
         */
        private void initData() {
                CompanyController companyController = null;
                try {
                        companyController = new CompanyController();
                        company = companyController.retrieveCompany(jobadvertisement.getCompanyID());
                } catch (Exception e) {
                        logger.log(Level.SEVERE, null, e);
                }
                resetForm();
                setEditable(false);
        }

        /**
         * To set company ID 
         * @param companyID
         */
        public void setCompanyId(String companyID) {
                textCompanyID.setText(companyID);
        }

        /**
         *
         * @param companyName
         */
        public void setCompanyName(String companyName) {
                labelCompanyName.setText(companyName);
        }

        /**
         * This function to set display mode (Writeable or Read-Only).
         * @param Editable Flag if the form in editable mode.
         */
        private void setEditable(boolean editable) {

                textCompanyID.setEditable(editable);
                btnSearchCompany.setEnabled(editable);
                textJobTitle.setEditable(editable);
                textJobLocation.setEditable(editable);
                textJobStartDate.setEditable(editable);
                textJobDescription.setEditable(editable);
                textCompanyDepartment.setEditable(editable);
                textTechnicalSkills.setEditable(editable);
                textManagementSkills.setEditable(editable);
                textMaxSalary.setEditable(editable);
                textMinSalary.setEditable(editable);
                textStartDate.setEditable(editable);
                textFinishDate.setEditable(editable);  
                if (jobadvertisement.isDeleted( )) {
                        labelStatusMsg = "[Advertisement is deleted] ";
                } else if (jobadvertisement.isWithdrawn( )) {
                        labelStatusMsg = "[Advertisement is withdrawn] "; 
                } 
                if (jobadvertisement.isWithdrawn( ) || jobadvertisement.isDeleted(  ) ) {

                        btnUpdate.setVisible(false);
                        btnReset.setVisible(false);
                        btnWithdraw.setVisible(false);
                        btnEdit.setVisible(false);
                }
                labelNoteMsg.setText(labelStatusMsg);
                if (jobadvertisement.isDeleted( ))
                        btnDelete.setVisible(false);
                 

        }

        /**
         * Set the jobadvertisement object
         * @param jobadvertisement
         */
        public void setJobAdvertisement(JobAdvertisement jobadvertisement) {
                this.jobadvertisement = jobadvertisement;
              
                initData();
        }

        /**
         * Get the jobadvertisement object
         * @return jobadvertisement
         */
        public JobAdvertisement getJobAdvertisement() {
                return this.jobadvertisement;
        }
        /**
         * To attach component to the form
         * @param c
         * @param gridx
         * @param gridy
         * @param gridwidth
         * @param gridheight
         * @param fill
         */
        @Override
        public void attachComponent(Component c, int gridx, int gridy, int gridwidth, int gridheight, int fill) {
                GridBagConstraints constraint = new GridBagConstraints();
                constraint.gridx = gridx;
                constraint.gridy = gridy;
                constraint.gridwidth = gridwidth;
                constraint.gridheight = gridheight;
                constraint.fill = fill;
                constraint.insets = new Insets(4, 4, 4, 4);
                constraint.weightx = 1.0;
                constraint.weighty = 1.0;
                inputPanel.add(c);
                inputLayout.setConstraints(c, constraint);
        }


        /**
         * Reset field value.
         */
        @Override
        public void resetForm() {
                labelErrorMessage.setText(""); 
                textCompanyID.setText(jobadvertisement.getCompanyID());
                labelCompanyName.setText(company.getName());
                textStartDate.setText(jobadvertisement.getStartDate());
                textFinishDate.setText(jobadvertisement.getFinishDate());
                textJobTitle.setText(jobadvertisement.getJobTitle());
                textJobDescription.setText(jobadvertisement.getJobDescription());
                textJobLocation.setText(jobadvertisement.getJobLocation());
                textJobStartDate.setText(jobadvertisement.getJobStartDate());
                textCompanyDepartment.setText(jobadvertisement.getCompanyDepartment());
                textTechnicalSkills.setText(jobadvertisement.getTechnicalSkills());
                textManagementSkills.setText(jobadvertisement.getManagementSkills());
                textMinSalary.setText(String.valueOf(jobadvertisement.getMinSalary()));
                textMaxSalary.setText(String.valueOf(jobadvertisement.getMaxSalary()));
                btnUpdate.setVisible(true);
                btnReset.setVisible(true);
                btnWithdraw.setVisible(true);
                btnEdit.setVisible(true);
                btnDelete.setVisible(true);
                labelStatusMsg = " Press 'Edit' to update";

        }

     /**
        * To handle the action to update the job advertisement when 'update' has been pressed.
        */
        class UpdateActionListener implements ActionListener {

                private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

                public void actionPerformed(ActionEvent e) {
                        //get all the input
                        String companyID = textCompanyID.getText();
                        String startDate = textStartDate.getText();
                        String finishDate = textFinishDate.getText();
                        String jobTitle = textJobTitle.getText();
                        String jobDescription = textJobDescription.getText();
                        String jobLocation = textJobLocation.getText();
                        String jobStartDate = textJobStartDate.getText();
                        String jobCompanyDepartment = textCompanyDepartment.getText();
                        String jobTechnicalSkills = textTechnicalSkills.getText();
                        String jobManagementSkills = textManagementSkills.getText();
                        String jobMinSalary = textMinSalary.getText();
                        String jobMaxSalary = textMaxSalary.getText();

                        //do validation
                        if (null == companyID || "".equalsIgnoreCase(companyID)) {
                                labelErrorMessage.setText("Please provide Company ID");
                                return;
                        }

                        if (null == startDate || "".equalsIgnoreCase(startDate)) {
                                labelErrorMessage.setText("Please provide Job Advertisement Start Date");
                                return;
                        } else if (startDate.length() != dateFormat.toPattern().length()) {
                                labelErrorMessage.setText("Incorrect Date format for Job Advertisement Start Date");
                                return;
                        } else {
                                dateFormat.setLenient(false);
                                try {
                                        //parse the startDate parameter
                                        dateFormat.parse(startDate.trim());
                                } catch (ParseException pe) {
                                        labelErrorMessage.setText(pe.getMessage());
                                        return;
                                }
                        }

                        if (null == finishDate || "".equalsIgnoreCase(finishDate)) {
                                labelErrorMessage.setText("Please provide Job Advertisement Finish Date");
                                return;
                        } else if (finishDate.length() != dateFormat.toPattern().length()) {
                                labelErrorMessage.setText("Incorrect Date format for Job Advertisement Finish Date");
                                return;
                        } else {
                                dateFormat.setLenient(false);
                                try {
                                        //parse the startDate parameter
                                        dateFormat.parse(startDate.trim());
                                } catch (ParseException pe) {
                                        labelErrorMessage.setText(pe.getMessage());
                                        return;
                                }
                        }

                        if (null == jobTitle || "".equalsIgnoreCase(jobTitle)) {
                                labelErrorMessage.setText("Please provide Job Advertisement Title");
                                return;
                        }

                        if (null == jobDescription || "".equalsIgnoreCase(jobDescription)) {
                                labelErrorMessage.setText("Please provide Job Advertisement Title");
                                return;
                        }

                        float minSalary = 0;
                        if (null == jobMinSalary || "".equalsIgnoreCase(jobMinSalary)) {
                                jobMinSalary = "0";
                        }
                        if (jobMinSalary != null) {
                                try {
                                        minSalary = Float.parseFloat(jobMinSalary);
                                } catch (NumberFormatException nfx) {
                                        labelErrorMessage.setText(nfx.getMessage());
                                        return;
                                }
                        }

                        float maxSalary = 0;
                        if (null == jobMaxSalary || "".equalsIgnoreCase(jobMaxSalary)) {
                                jobMaxSalary = "0";
                        }
                        if (jobMaxSalary != null) {
                                try {
                                        maxSalary = Float.parseFloat(jobMaxSalary);
                                } catch (NumberFormatException nfx) {
                                        labelErrorMessage.setText(nfx.getMessage());
                                        return;
                                }
                        }

                        //save it
                        jobadvertisement.setJobTitle(jobTitle);
                        jobadvertisement.setJobDescription(jobDescription);
                        jobadvertisement.setJobLocation(jobLocation);
                        jobadvertisement.setStartDate(startDate);
                        jobadvertisement.setCompanyDepartment(jobCompanyDepartment);
                        jobadvertisement.setTechnicalSkills(jobTechnicalSkills);
                        jobadvertisement.setManagementSkills(jobManagementSkills);
                        jobadvertisement.setMinSalary(minSalary);
                        jobadvertisement.setMaxSalary(maxSalary);
                        jobadvertisement.setJobStartDate(jobStartDate);
                        jobadvertisement.setCompanyID(companyID);

                        
                        boolean success = false;
                        try {
                                JobAdvertisementController jobadvertisementController = new JobAdvertisementController();
                                success = jobadvertisementController.updateJobAdvertisement(jobadvertisement);
                        } catch (Exception ex) {
                                logger.log(Level.SEVERE, null, ex);
                        }

                        if (success) {
                                displayMessage("Information", "Job Advertisement has successfully updated.");
                                close();
                                parent.resetForm();
                        } else {
                                displayMessage("Error", "Failed to update Job Advertisement.");
                        }

                }
        }

        /**
        * To handle the action to exit from the form when 'Cancel' has been pressed.
        */
        class CancelActionListener implements ActionListener {
                public void actionPerformed(ActionEvent e) {
                        close();
                }
        }

        /**
        * To handle the action to reset the form when 'Reset' has been pressed.
        */
        class ResetActionListener implements ActionListener {

                public void actionPerformed(ActionEvent e) {
                        resetForm();
                }
        }

       /**
        * To handle the action to change the edit mode when 'Edit' has been pressed.
        */
        class EditActionListener implements ActionListener {

                public void actionPerformed(ActionEvent e) {
                        btnSearchCompany.setEnabled(true);
                        textCompanyID.setEditable(true);
                        textStartDate.setEditable(true);
                        textFinishDate.setEditable(true);
                        textJobTitle.setEditable(true);
                        textJobDescription.setEditable(true);
                        textJobLocation.setEditable(true);
                        textJobStartDate.setEditable(true);
                        textCompanyDepartment.setEditable(true);
                        textTechnicalSkills.setEditable(true);
                        textManagementSkills.setEditable(true);
                        textMinSalary.setEditable(true);
                        textMaxSalary.setEditable(true);
                        labelNoteMsg.setText("Press 'Save' to comit your changes");
                }
        }

       /**
        * To handle the action for company search
        */
        class SearchCompanyActionListener implements ActionListener {
                public void actionPerformed(ActionEvent e) {
                        AdvertiserListCompanyForm companyForm = AdvertiserListCompanyForm.getInstance(AdvertiserUpdateJobAdvertisementForm.this);
                        companyForm.setVisible(true);
                }
        }

       /**
        * To handle the action to widthdraw the job advertisement when 'withdraw' has been pressed.
        */
        class WithdrawActionListener implements ActionListener {

                public void actionPerformed(ActionEvent e) {

                        //set withdrawn date
                        Calendar currentDate = Calendar.getInstance();
                        jobadvertisement.setWithdrawn(currentDate.getTime().toString());

                        //update to persistent
                        boolean success = false;
                        JobAdvertisementController jobadvertisementController = null;
                        try {
                                jobadvertisementController = new JobAdvertisementController();
                                success = jobadvertisementController.updateJobAdvertisement(jobadvertisement);
                        } catch (Exception ex) {
                                logger.log(Level.SEVERE, null, ex);
                        }

                        if (success) {
                                displayMessage("Information","Withdrawn successfully");
                                close();
                                parent.resetForm();
                        } else {
                                displayMessage("Error","Failed to Withdraw ");
                        }

                }
        }

        /**
        * To handle the action to delete the job advertisement when 'Delete' has been pressed.
        */
        class DeleteActionListener implements ActionListener {

                public void actionPerformed(ActionEvent e) {

                        //set deleted
                        Calendar currentDate = Calendar.getInstance();
                        jobadvertisement.setDeleted(currentDate.getTime().toString());

                        boolean success = false;
                        JobAdvertisementController jobadvertisementController = null;
                        try {
                                jobadvertisementController = new JobAdvertisementController();
                                success = jobadvertisementController.updateJobAdvertisement(jobadvertisement);
                        } catch (Exception ex) {
                                logger.log(Level.SEVERE, null, ex);
                        }

                        if (success) {
                                displayMessage("Information", "Jobadvertisement has successfully deleted");
                                close();
                                parent.resetForm();
                        } else {
                                displayMessage("Error", "Failed to deleted JobAdvertisement");
                        }

                }
        }

       /**
        * To handle the action  to view the job response  when 'ViewResponse' has been pressed.
        */
        class ViewResponsesActionListener implements ActionListener {

                public void actionPerformed(ActionEvent e) {

                        ResponseController responseController = new ResponseController();
                        try {
                                if (responseController.isResponsed(jobadvertisement.getID())) {
                                        MainController.getInstance().gotoScreen(MainController.ADVERTISER_LIST_RESPONSE_FORM, instance);
                                } else {
                                        displayMessage("Information", "There is no response.");
                                }
                        } catch (Exception ex) {
                                logger.log(Level.SEVERE, null, ex);
                        }
                }
        }
}
